package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.dto.SMSSendDTO;
import cn.itsource.hrm.feignclients.RedisFeignClient;
import cn.itsource.hrm.service.IVerifyCodeService;
import cn.itsource.hrm.util.AjaxResult;
import cn.itsource.hrm.util.HttpUtil;
import cn.itsource.hrm.util.StrUtils;
import cn.itsource.hrm.util.VerifyCodeUtils;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisFeignClient redisFeignClient ;

    @Override
    public String createImageCode(String imageCodeKey) throws IOException {
        //1.判断参数
        if(!StringUtils.hasLength(imageCodeKey)){
            throw new RuntimeException("无效的imageCodeKey");
        }
        //2.使用UUID生成验证码的值
        String imageCodeValue = UUID.randomUUID().toString().substring(0,4);

        //3.以imageCodeKey为key把验证码的值存储到Redis , 设置过期时间
        redisFeignClient.setex(imageCodeKey,300,imageCodeValue);

        //4.把验证码的值合并成图片
        //5.把图片进行base64编码
        //6.返回编码后的字符串
        return VerifyCodeUtils.verifyCode(135,40,imageCodeValue);
    }

    @Override
    public void sendSmsCode(Map<String, String> map) {
        //1.参数基本判断
        String imageCode = map.get("imageCode");
        String imageCodeKey = map.get("imageCodeKey");
        String phone = map.get("mobile");
        if(!StringUtils.hasLength(imageCode) || !StringUtils.hasLength(imageCodeKey) || !StringUtils.hasLength(phone)  ){
            throw new RuntimeException("无效的参数");
        }

        //2.校验图片验证码===============================================
        //2.1.根据参数中的key,从Redis中获取图片验证码的值
        AjaxResult ajaxResult = redisFeignClient.get(imageCodeKey);
        if(!ajaxResult.isSuccess() || ajaxResult.getResultObj() == null){
            throw new RuntimeException("无效的图片验证码，请重新发送");
        }
        //2.2.redis中的图片验证码的值和参数中的验证码的值比较
        //图片验证码的值
        String imageCodeValue = ajaxResult.getResultObj().toString();
        if(!imageCodeValue.equals(imageCode)){
            throw new RuntimeException("错误的图片验证码，请重新发送");
        }

        //验证码的key sms:182444444444  ->   sms:182444445555
        String smsCodeRedisKey = "sms:"+phone;

        Date nowDate = new Date();

        //3.获取上一次验证码发送记录=======================================
        AjaxResult lastAjaxResult = redisFeignClient.get(smsCodeRedisKey);

        //验证码
        String smsCode = null;

        if(lastAjaxResult.isSuccess() && lastAjaxResult.getResultObj() != null){
            //3.1.如果上一次有
            //3.1.1.判断上一次发送发送时间和当前时间要大于 60s(60000)，
            SMSSendDTO lastSmsSendDTO = JSON.parseObject(lastAjaxResult.getResultObj().toString(), SMSSendDTO.class);
            if((nowDate.getTime() - lastSmsSendDTO.getSendTime()) < 60000){
                throw new RuntimeException("发送频繁，请稍后重新发送");
            }

            // -> 使用上一次发送验证码继续发
            smsCode = lastSmsSendDTO.getCode();
        }else{
            //3.2.如果上一次没有
            //3.2.1.创建新的验证码
            smsCode = StrUtils.getRandomString(6);
        }

        //4.存储验证码发送记录到Redis(或者覆盖：改时间) ：时间，验证码，手机
        String senDTOJson = JSON.toJSONString(new SMSSendDTO(smsCode, phone, nowDate.getTime()));

        redisFeignClient.setex(smsCodeRedisKey,300,senDTOJson);

        //5.调用三方短信网关，发送短信
        String sendMessage = "您的注册验证码为["+smsCode+"]，请在5分钟内使用[源码科技]";
        System.out.println(sendMessage);

        Map<String,String> smsMap = new HashMap<>();
        smsMap.put("Uid","hanfy");
        smsMap.put("Key","d41d8cd98f00b204e980");
        smsMap.put("smsMob",phone);
        smsMap.put("smsText",sendMessage);

        String result = HttpUtil.sendPost("http://utf8.api.smschinese.cn/",smsMap);
        if(Integer.valueOf(result) == -1){
            throw new RuntimeException("短信发送失败：【-1 没有账户】，请联系管理员");
        }
        if(Integer.valueOf(result) < 0){
            throw new RuntimeException("短信发送失败");
        }
        //6.存储发送记录到MYSQL，作为平台统计，监控的依据
    }
}

